package com.foohoo.benchmark.cpu;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 测试CPU的分支预测对性能的提升
 * via https://segmentfault.com/a/1190000006889989
 * Benchmark                  Mode  Cnt  Score   Error  Units
 * BranchPrediction.sorted    avgt    3  3.742 ± 2.509  ns/op
 * BranchPrediction.unsorted  avgt    3  9.431 ± 6.577  ns/op
 * 一句话结论: 排序数组在分支预测中有很高的正确率，可以有效提升性能
 *
 * @author mzdbxqh
 * @date 2020-10-22 14:22
 **/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(1)
@Threads(1)
@State(Scope.Benchmark)
public class BranchPrediction {

	private static final int COUNT = 1024 * 1024;

	private byte[] sorted;
	private byte[] unsorted;

	@Setup
	public void setup() {
		sorted = new byte[COUNT];
		unsorted = new byte[COUNT];
		Random random = new Random(1234);
		random.nextBytes(sorted);
		random.nextBytes(unsorted);
		Arrays.sort(sorted);
	}

	@Benchmark
	@OperationsPerInvocation(COUNT)
	public void sorted(Blackhole bh1, Blackhole bh2) {
		for (byte v : sorted) {
			if (v > 0) {
				bh1.consume(v);
			} else {
				bh2.consume(v);
			}
		}
	}

	@Benchmark
	@OperationsPerInvocation(COUNT)
	public void unsorted(Blackhole bh1, Blackhole bh2) {
		for (byte v : unsorted) {
			if (v > 0) {
				bh1.consume(v);
			} else {
				bh2.consume(v);
			}
		}
	}

}
